package com.emperorque.mathpractice.service;

import com.emperorque.mathpractice.model.Expression;
import com.emperorque.mathpractice.model.ExpressionType;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

/**
 * 算式生成器实现类
 * 生成100以内的加减法算式
 */
public class SimpleExpressionGenerator implements ExpressionGenerator {
    
    private static final int MIN_NUMBER = 0;
    private static final int MAX_NUMBER = 100;
    private final Random random;
    
    public SimpleExpressionGenerator() {
        this.random = new Random();
    }
    
    /**
     * 用于测试的构造函数，可以指定随机数种子
     */
    public SimpleExpressionGenerator(long seed) {
        this.random = new Random(seed);
    }
    
    @Override
    public List<Expression> generate(int count, ExpressionType type) {
        if (count <= 0) {
            throw new IllegalArgumentException("生成数量必须大于0");
        }
        if (type == null) {
            throw new IllegalArgumentException("算式类型不能为空");
        }
        
        Set<String> expressionSet = new HashSet<>();
        List<Expression> expressions = new ArrayList<>();
        
        int maxAttempts = count * 100; // 防止无限循环
        int attempts = 0;
        
        while (expressions.size() < count && attempts < maxAttempts) {
            attempts++;
            Expression expr = type == ExpressionType.SIMPLE 
                ? generateSimpleExpression() 
                : generateMixedExpression();
            
            // 确保不重复
            if (expressionSet.add(expr.getExpressionString())) {
                expressions.add(expr);
            }
        }
        
        if (expressions.size() < count) {
            throw new RuntimeException("无法生成足够的不重复算式");
        }
        
        return expressions;
    }
    
    /**
     * 生成简单算式（只包含一个运算符）
     */
    private Expression generateSimpleExpression() {
        int num1 = random.nextInt(MAX_NUMBER + 1);
        int num2 = random.nextInt(MAX_NUMBER + 1);
        boolean isAddition = random.nextBoolean();
        
        String expressionString;
        int result;
        
        if (isAddition) {
            // 加法：确保结果不超过100
            if (num1 + num2 > MAX_NUMBER) {
                num2 = MAX_NUMBER - num1;
            }
            result = num1 + num2;
            expressionString = num1 + " + " + num2;
        } else {
            // 减法：确保结果不小于0
            if (num1 < num2) {
                int temp = num1;
                num1 = num2;
                num2 = temp;
            }
            result = num1 - num2;
            expressionString = num1 + " - " + num2;
        }
        
        return new Expression(expressionString, result, ExpressionType.SIMPLE);
    }
    
    /**
     * 生成混合算式（包含2-3个运算符）
     */
    private Expression generateMixedExpression() {
        int operatorCount = 2 + random.nextInt(2); // 2或3个运算符
        List<Integer> numbers = new ArrayList<>();
        List<Character> operators = new ArrayList<>();
        
        // 生成第一个数字
        numbers.add(random.nextInt(MAX_NUMBER + 1));
        
        // 生成运算符和后续数字
        for (int i = 0; i < operatorCount; i++) {
            char operator = random.nextBoolean() ? '+' : '-';
            operators.add(operator);
            numbers.add(random.nextInt(MAX_NUMBER + 1));
        }
        
        // 从左到右计算结果
        int result = numbers.get(0);
        StringBuilder expressionString = new StringBuilder(String.valueOf(numbers.get(0)));
        
        for (int i = 0; i < operators.size(); i++) {
            char operator = operators.get(i);
            int num = numbers.get(i + 1);
            
            expressionString.append(" ").append(operator).append(" ").append(num);
            
            if (operator == '+') {
                result += num;
            } else {
                result -= num;
            }
        }
        
        // 如果结果超出范围，重新生成
        if (result < MIN_NUMBER || result > MAX_NUMBER) {
            return generateMixedExpression();
        }
        
        return new Expression(expressionString.toString(), result, ExpressionType.MIXED);
    }
}
